/**
 * 题目链接：2025/10/03 考试 T1 组模拟赛
 * 完成时间: 2025-10-03 10:30
 * 简要思路：枚举最大值，尽可能地让最小值最大，使用树状数组与双指针维护。
 */
#include <bits/stdc++.h>
#define range(i, b, e) for (auto i(b); i != (e); i++)
#define rep(i, b, e) for (auto i(b); i <= (e); i++)
#define req(i, b, e) for (auto i(b); i >= (e); i--)
using namespace std;
typedef long long LL;
typedef long double LD;
typedef pair<int, int> Pii;

const int N = 1e6, M = 4e6;
int n, cnt, mn, mx, ans = 2e9;
int lst[N+5];
struct S {int val, id, tag;} a[M+5];

void upd(int i) {
	int id = a[i].id;
	a[lst[id]].tag--;
	a[lst[id] = i].tag++;
	while (!a[mn].tag) mn++;
	ans = min(ans, a[mx].val - a[mn].val);
}

int main() {
	freopen("contest.in", "r", stdin);
	freopen("contest.out", "w", stdout);
	ios::sync_with_stdio(false);
	cin.tie(nullptr); cout.tie(nullptr);
	cin >> n;
	for (int i = 1, k; i <= n; i++) {
		cin >> k;
		int mn = 1;
		rep(j, 1, k) {
			cin >> a[cnt + j].val, a[cnt + j].id = i;
			if (a[cnt + mn].val > a[cnt + j].val) mn = j;
		}
		a[cnt + mn].tag++;
		cnt += k;
	}
	sort(a + 1, a + cnt + 1, [](S x, S y) {return x.val < y.val;});
//	rep(i, 1, cnt) {
//	cout << a[i].val << ',' << a[i].id;
//	if (a[i].tag) cout << "←";
//	cout << ' ';
//	}
//	cout << '\n';

	rep(i, 1, cnt) {
		if (a[i].tag) {
			lst[a[i].id] = i;
			mx = i;
		}
	}

	rep(i, 1, mx) upd(i);
	for (mx++; mx <= cnt; mx++) upd(mx);
	cout << ans;
	return 0;
}
